package com.xydtech.ecard.login.controller;

import com.alibaba.fastjson.JSONObject;
import com.xydtech.common.annotation.PassToken;
import com.xydtech.common.annotation.RsaRequest;
import com.xydtech.common.cache.EhcacheUtil;
import com.xydtech.common.core.domain.entity.SysUser;
import com.xydtech.common.enums.ApiContant;
import com.xydtech.common.enums.ResultStatus;
import com.xydtech.common.exception.ApiException;
import com.xydtech.common.model.ResponseModel;
import com.xydtech.common.token.JwtTokenUtil;
import com.xydtech.common.utils.spring.SpringUtils;
import com.xydtech.common.utils.string.StringUtil;
import com.xydtech.constant.EcardApiConstants;
import com.xydtech.ecard.ecard.controller.EcardApiBaseController;
import com.xydtech.ecard.user.domain.EcardApiEcardRegistInfo;
import com.xydtech.ecard.user.service.IEcardApiEcardRegistInfoService;
import com.xydtech.system.domain.SysWechatApplet;
import com.xydtech.system.service.ISysDeptService;
import com.xydtech.system.service.ISysUserService;
import com.xydtech.system.service.ISysWechatAppletService;
import io.swagger.annotations.*;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

@Controller
@Api(tags = "电子名片-用户登录")
@RequestMapping("/ecardSaasApi/login")
public class EcardApiLoginController extends EcardApiBaseController {

    @Autowired
    private IEcardApiEcardRegistInfoService ecardRegistInfoService;

    @Autowired
    private ISysWechatAppletService sysWeChatAppletService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysWechatAppletService wechatAppletService;
    @Autowired
    private ISysDeptService sysDeptService;
    private static CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);


    /**
     * 电子名片登录
     * @param ecardRegistInfo
     * @return
     */
    @PassToken
    @PostMapping
    @ResponseBody
    @ApiImplicitParams({@ApiImplicitParam(name = "ecardRegistInfo", value = "工作室信息", dataType = "EcardApiEcardRegistInfo", dataTypeClass = EcardApiEcardRegistInfo.class, paramType = "body", required = true)})
    @ApiResponses({@ApiResponse(code = 0, message = "OK", response = ResponseModel.class)})
    @ApiOperation(value = "电子名片-电子名片登录", notes = "电子名片-电子名片登录", produces = MediaType.APPLICATION_JSON_VALUE)
    @RsaRequest
    public ResponseModel login(@RequestBody @Validated EcardApiEcardRegistInfo ecardRegistInfo) {
        String salt = getSalt();//盐值
        /**
         * 思路：
         * 1. 首先根据用户注册信息（userCode，wechatName，phoneno）查询下是否在sys_user表中存在，存在说明有效，不存在说明无效
         * 2. 然后再用userCode查询注册表（ecard_regist_info），判断userCode是否已经被占用了
         *  2.1 如果有占用，直接返回被xxxx用户名的xxxx手机号的用户占用了
         *  2.2 如果没有占用，新增用户信息到表中，roles为4-营销经理
         */
        String userCode = ecardRegistInfo.getUserCode();
        String wechatName = ecardRegistInfo.getWechatName();
        String phoneno = ecardRegistInfo.getPhoneno();

        //
        /**
         * 查询sys_user表的user_code（userCode）、user_name（wechatName）、phonenumber（phoneno）是否存在对应的用户
         */
        SysUser user = userService.selectUserByWechatRegistInfo(userCode, wechatName, phoneno, salt);
        if (user == null) {
            throw new ApiException(ResultStatus.NOT_FOUND_CUSTOMER_ERROR);
        }

        EcardApiEcardRegistInfo registInfo = ecardRegistInfoService.selectEcardApiEcardRegistInfoByUserCode(userCode, salt);
        if (registInfo != null) {
            return ResponseModel.error("该员工编号已被用户名为：" + registInfo.getWechatName() + "占用，请联系管理员进行解绑！");
        }
        ///当前小程序id
        SysWechatApplet wechatApplet = getAppIdByDeptId(user.getDeptId());
        String appId = wechatApplet.getAppid();
        //获取openid
        String openId = getOpenIdByCode(appId, ecardRegistInfo.getCode());
        /**
         * 根据openId和获取用户信息，
         * 如果有注册信息，在判断是否有userCode
         * 有就直接返回token
         * 没有说明是注销过的，更新userCode到注册表中，再返回token
         * 没有就新增再返回token
         */
        EcardApiEcardRegistInfo ecardRegist = ecardRegistInfoService.selectEcardApiEcardRegistInfoByOpenId(openId, salt);
        //生成Token信息
        String accessToken = "";
        if (ecardRegist != null){
            if (StringUtil.objIsNullOrEmpty(ecardRegist.getUserCode())){//注销状态
                //注销过再次登录时，输入手机号和注册信息中的手机号不一致，提示
                if (!ecardRegist.getPhoneno().equals(phoneno)) {
                    return ResponseModel.error("该账号已被手机号为：" + ecardRegist.getPhoneno() + "占用，请联系管理员！");
                }
                EcardApiEcardRegistInfo regist = new EcardApiEcardRegistInfo();
                regist.setRegistId(ecardRegist.getRegistId());
                regist.setUserCode(userCode);
                ecardRegistInfoService.updateUserCode(regist, salt);
            }
            accessToken = getToken(openId, ecardRegist.getRegistId());
        } else {
            ecardRegistInfo.setWechatId(openId);
            //默认客户经理
            ecardRegistInfo.setRoles("4");
            ecardRegistInfoService.insertEcardApiEcardRegistInfo(ecardRegistInfo, salt);
            accessToken = getToken(openId, ecardRegistInfo.getRegistId());
        }
        return ResponseModel.ok(accessToken);
    }

    /**
     * 电子名片校验是否登录
     * @param json
     * @return
     */
    @PassToken
    @PostMapping("/verifyIsLogin")
    @ResponseBody
    @ApiOperation(value = "电子名片-电子名片校验是否登录", notes = "电子名片-电子名片校验是否登录", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiResponses({@ApiResponse(code = 0, message = "OK", response = ResponseModel.class)})
    @RsaRequest
    public ResponseModel verifyIsLogin(@RequestBody String json) {
        String salt = getSalt();//盐值
        //校验code是否为空
        if (StringUtil.isNullOrEmpty(json)) {
            throw new ApiException(ResultStatus.PARAMETER_MISSING);
        }
        JSONObject jsonObject = JSONObject.parseObject(json);
        String code = jsonObject.getString("code");
        String appId = jsonObject.getString("appId");
        //思路：
          //1. 首先获取到openid，根据openid查询ecard_regist_info信息表
          //1.1 如果查询不到用户信息，返回1，前端根据1判断去调用登录接口
          //1.2 如果能查询到，直接根据用户的userid和openid生成token返回，说明已经登录过
        String openId = getOpenIdByCode(appId, code);
        //校验openid的获取情况
        if (StringUtil.isNullOrEmpty(openId)) {
            throw new ApiException(ResultStatus.FAILED_TO_GET_OPENID);
        }
        //根据openId获取用户信息
        EcardApiEcardRegistInfo ecardRegistInfo = ecardRegistInfoService.selectEcardApiEcardRegistInfoByOpenId(openId, salt);

        if (ecardRegistInfo == null || StringUtil.objIsNullOrEmpty(ecardRegistInfo.getUserCode())) {
            return ResponseModel.ok(1);
        }else {
            //生成Token信息
            String accessToken = getToken(openId, ecardRegistInfo.getRegistId());
            return ResponseModel.ok(accessToken);
        }
    }

    /**
     * 根据code获取用户的openId
     * @Title getOpenIdByCode
     * @param code:小程序端wx.login获取到的code
     * @return java.lang.String
     * @exception
     * @author Daniel
     * @Date 2020/7/30 9:36
     **/
    private String getOpenIdByCode(String appId, String code) {

        //获取配置的小程序的appid和secret
        SysWechatApplet sysWechatApplet = sysWeChatAppletService.getWechatAppletByAppId(ApiContant.APPLETTYPE_ECARD, appId);

        String requestUrl = sysWechatApplet.getGetOpenIdUrl() + "appid=" + sysWechatApplet.getAppid() + "&secret=" + sysWechatApplet.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";

        String openId = null;
        RestTemplate restTemplate = new RestTemplate();
        String loginInfoStr = restTemplate.getForObject(requestUrl, String.class);

        //获取返回内容中的openId信息
        JSONObject openIdInfoObj = JSONObject.parseObject(loginInfoStr);
        openId = openIdInfoObj.getString("openid");
        return openId;
    }

    /**
     * 获取token
     * @param openid
     * @param custId
     * @return
     */
    private String getToken(String openid, Long custId) {
        String token = JwtTokenUtil.generateToken(custId.toString(), openid);
        //向ehcache存的key值
        String cookieKey = EcardApiConstants.JWT_KEY_USER_ID + custId;
        if (StringUtil.isNullOrEmpty(EhcacheUtil.getEcardAccessToken(cookieKey, cacheManager))) {
            EhcacheUtil.setEcardAccessToken(cookieKey, token, cacheManager);
        } else {
            EhcacheUtil.removeEcardAccessToken(cookieKey, cacheManager);
            EhcacheUtil.setEcardAccessToken(cookieKey, token, cacheManager);
        }

        return token;
    }
}
